<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>动态粒子爱心</title>
    <style>
        body {
            margin: 0;
            overflow: hidden;
            background-color: black;
        }
        canvas {
            display: block;
        }
    </style>
</head>
<body>
    <canvas id="heartCanvas"></canvas>

    <script>
        const canvas = document.getElementById('heartCanvas');
        const ctx = canvas.getContext('2d');
        canvas.width = window.innerWidth;
        canvas.height = window.innerHeight;

        const CANVAS_CENTER_X = canvas.width / 2;
        const CANVAS_CENTER_Y = canvas.height / 2;
        const IMAGE_ENLARGE = 11;
        const HEART_COLOR = '#FF69B4';
        const particles = [];
        const numberOfParticles = 1000; // 粒子数量
        const maxFrame = 200; // 动画帧数

        // 心形方程
        function heartFunction(t, enlargeRatio = IMAGE_ENLARGE) {
            let x = 16 * Math.pow(Math.sin(t), 3);
            let y = -(13 * Math.cos(t) - 5 * Math.cos(2 * t) - 2 * Math.cos(3 * t) - Math.cos(4 * t));
            x *= enlargeRatio;
            y *= enlargeRatio;
            x += CANVAS_CENTER_X;
            y += CANVAS_CENTER_Y;
            return { x: x, y: y };
        }

        // 粒子类
        class Particle {
            constructor(x, y) {
                this.x = x;
                this.y = y;
                this.size = Math.random() * 2 + 1; // 随机大小
                this.speedX = Math.random() * 0.5 - 0.5; // 随机速度
                this.speedY = Math.random() * 0.5 - 0.5;
            }

            update() {
                this.x += this.speedX;
                this.y += this.speedY;
            }

            draw() {
                ctx.fillStyle = HEART_COLOR;
                ctx.beginPath();
                ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
                ctx.fill();
            }
        }

        // 创建粒子
        function createParticles() {
            for (let i = 0; i < numberOfParticles; i++) {
                const t = Math.random() * 2 * Math.PI;
                const pos = heartFunction(t);
                particles.push(new Particle(pos.x, pos.y));
            }
        }

        // 动画函数
        function animate(frame = 0) {
            ctx.clearRect(0, 0, canvas.width, canvas.height); // 清除画布

            // 绘制粒子
            particles.forEach((particle, index) => {
                particle.update();
                particle.draw();

                // 如果粒子超出画布边界则重置
                if (particle.x < 0 || particle.x > canvas.width || particle.y < 0 || particle.y > canvas.height) {
                    const t = Math.random() * 2 * Math.PI;
                    const pos = heartFunction(t);
                    particle.x = pos.x;
                    particle.y = pos.y;
                }
            });

            // 递归调用动画帧
            if (frame < maxFrame) {
                requestAnimationFrame(() => animate(frame + 1));
            }
        }

        // 初始化函数
        function init() {
            createParticles();
            animate();
        }

        init();
    </script>
</body>
</html>
